package services.common;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import models.common.entity.t_scroe;
import models.common.entity.t_scroe_rule;
import models.common.entity.t_scroe_take_notes;
import models.common.entity.t_user;
import services.base.BaseService;

import common.constants.ScroeRuleKey;
import common.enums.NoticeScene;
import common.utils.Factory;
import common.utils.LoggerUtil;
import common.utils.PageBean;
import common.utils.ResultInfo;
import common.utils.number.Arith;

import daos.common.ScroeDao;

/**
 * 积分账户service
 *@author binghui.zhou
 *@version 2017年8月25日 上午10:29:47
 */
public class ScroeService extends BaseService<t_scroe> {
	
	protected static UserFundService userFundService = Factory.getService(UserFundService.class);
	
	protected static UserService userService = Factory.getService(UserService.class);
	
	protected static ScroeRuleService scroeRuleService = Factory.getService(ScroeRuleService.class);
	
	protected static ScroeTakeNotesService scroeTakeNotesService = Factory.getService(ScroeTakeNotesService.class);
	protected static NoticeService noticeService = Factory.getService(NoticeService.class);
	private ScroeDao scroeDao;
	
	public ScroeService(){
		scroeDao = Factory.getDao(ScroeDao.class);
		super.basedao = scroeDao;
	}
	
	/**
	 * 创建积分账户
	 * @param id
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月25日
	 */
	public boolean saveScroe(Long id) {
		t_scroe scroe= new t_scroe();
		scroe.time = new Date();
		scroe.user_id = id;
		boolean bln = scroeDao.save(scroe);
		if (!bln){
			return false;
		}
		return true;
	}
	
	/**
	 * 后台统计 积分统计
	 * @param currPage
	 * @param pageSize
	 * @param userName
	 * @param type
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月25日
	 */
	public PageBean<Map<String, Object>> scroeUserStatistice(int currPage, int pageSize, String userName, int type,int exports) {
		return scroeDao.scroeUserStatistice(currPage,pageSize,userName,type,exports);
	}
	
	/**
	 * 后台积分清零
	 * @return
	 * @author binghui.zhou
	 * @param array 
	 * @createDate 2017年8月25日
	 */
	public ResultInfo clenScroe(long[] array) {
		ResultInfo result = new ResultInfo();
		for (long id :array){
			t_scroe scroe =findByID(id);
			if (scroe == null){
				result.code = -1;
				result.msg = "未找到对应的积分账户";
				return result;
			}
			int type = scroeDao.updateScroe(scroe);
			if (type < 1){
				result.code = -1;
				result.msg = "积分清零失败";
				return result;
			}
		}
		result.code = 1;
		result.msg = "积分清零成功";
		return result;
	}
	
	/**
	 * 根据用户ID查找积分账户
	 * @param userId
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月25日
	 */
	public t_scroe findScroe(long userId) {
		return scroeDao.findByColumn(" user_id=? ", userId);
	}
	
	/**
	 * 扣减积分
	 * @param id
	 * @param scroe
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月26日
	 */
	public boolean deductionScroe(long id,int scroe,int bid_scroe,int total_scroe){
		int type = scroeDao.deductionScroe(id,scroe,bid_scroe,total_scroe);
		if (type < 1){
			return false;
		}
		return true;
	}
	
	/**
	 * 积分增加
	 * @param id
	 * @param scroe
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月26日
	 */
	public boolean addDeductionScroe(long id,int scroe,int bid_scroe){
		int type = scroeDao.addDeductionScroe(id,scroe,bid_scroe);
		if (type < 1){
			return false;
		}
		return true;
	}
	
	/**
	 * 积分提现
	 * @param tScroe
	 * @return
	 * @author binghui.zhou
	 * @param scroe 
	 * @createDate 2017年8月26日
	 */
	public ResultInfo scroeWithdraw(Long userId, int scroe) {
		ResultInfo   result = new ResultInfo();
		if (scroe <= 0){
			result.code = -1;
			result.msg = "提现积分小于或者等于0，不可提现";
			return result;
		}
		
		//先查用户信息
		t_user user = userService.findByID(userId);
		if (null == user){
			result.code = -1;
			result.msg = "用户信息不完善请联系管理员";
			return result;
		}
		t_scroe tScroe = findScroe(userId);
		if (null == tScroe){
			result.code = -1;
			result.msg = "用户信息不完善请联系管理员";
			return result;
		}
		
		t_scroe_rule scrowRule = scroeRuleService.findScroeRule(ScroeRuleKey.SCROE_WITHDRAW);
		if (null == scrowRule){
			result.code = -1;
			result.msg = "提现规则有误请联系管理员";
			return result;
		}
		
		if (scroe > tScroe.scroe){
			result.code = -1;
			result.msg = "输入的提现积分不能打于可提现积分";
			return result;
		}
		
		if (scroe < scrowRule.scroe){
			result.code = -1;
			result.msg = "账户积分小于积分提现比例积分";
			return result;
		}
		
		result = userFundService.userFundSignCheck(userId);
		if (result.code < 1){
			return result;
		}
		double amount = countScroeReadyMoney(scroe,scrowRule.scroe,scrowRule.amount);
		
		boolean type = userFundService.userFundAdd(userId,amount);
		if (!type){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "资金更新失败");
			result.code = -1;
			result.msg = "资金更新失败";
			return result;
		}
		result = userFundService.userFundSignUpdate(userId);
		if (result.code < 1){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", result.msg);
			return result;
		}
		
		result = scroeWithdraw(tScroe,scrowRule,"积分提现",scroe);
		if (result.code < 1 ){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", result.msg);
			return result;
		}
		//通知用户
		Map<String, Object> sceneParame = new HashMap<String, Object>();
		sceneParame.put("user_name", user.company_full_name==null ?user.name:user.company_full_name );
		sceneParame.put("amount", amount );
		noticeService.sendSysNotice(tScroe.user_id, NoticeScene.INTEGRAL_WITHDRAWAL, sceneParame);		
		result.code = 1;
		result.msg = "积分提现成功";
		return result;
	}
	
	/**
	 *  根据积分比例计算所得现金
	 * @param scroe 积分
	 * @param ruleScroe 规则积分
	 * @return
	 * @author binghui.zhou
	 * @param amount 
	 * @createDate 2017年8月26日
	 */
	private double countScroeReadyMoney(int scroe,int ruleScroe, int amount){
		 BigDecimal b1 = new BigDecimal(Double.toString(scroe));  
		 BigDecimal b2 = new BigDecimal(Double.toString(ruleScroe));  
		 BigDecimal b3 = new BigDecimal(Double.toString(amount));  
		 
		 BigDecimal dou = b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);  
		 
		 return  dou.multiply(b3).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); 
	}
	
	
	/**
	 * 融通/投资手续费抵扣
	 * @param userId 用户ID
	 * @param amount 手续费金额
	 * @param name 描述
	 * @param type  状态 1融通  2投资
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月28日
	 */
	public ResultInfo investFinancingPoundage(long userId,double amount,String name,int type,String title){
		
		ResultInfo result = new ResultInfo();
		
		t_scroe scroe =findScroe(userId);
		if (null == scroe){
			result.code = -1;
			result.msg = "用户积分信息不全请联系管理员";
			result.obj = amount;
			return result;
		}
		//抵扣手续费规则
		t_scroe_rule scroeRule = null;
		if (type == 1){//融通
			scroeRule = scroeRuleService.findScroeRule(ScroeRuleKey.FINANCING_POUNDAGE);
		}
		else{//投资
			scroeRule = scroeRuleService.findScroeRule(ScroeRuleKey.INVEST_POUNDAGE);
		}
		if (null == scroeRule){
			result.code = -1;
			result.msg = "积分规则不全请联系管理员";
			result.obj = amount;
			return result;
		}
		//最大积分抵扣百分比
		t_scroe_rule deductionSettings = scroeRuleService.findScroeRule(ScroeRuleKey.DEDUCTION_SETTINGS);
		if (null == deductionSettings){
			result.code = -1;
			result.msg = "积分规则不全请联系管理员";
			result.obj = amount;
			return result;
		}
		if (deductionSettings.amount <= 0){
			result.code = 1;
			result.msg = "积分抵扣手续的比例为0";
			result.obj = amount;
			return result;
		}
		
		// 计算积分抵扣手续费并进行扣除积分
		result = countPoundage(scroeRule,deductionSettings,scroe,amount,name,title);
		
		if (result.code < 1){
			return result;
		}
		
		return result;
	}
	
	
	/**
	 * 进行计算扣除积分
	 * @param scroeRule 积分规则对象
	 * @param deductionSettings //积分抵扣手续费比例对象
	 * @param tScroe  积分账户对象
	 * @param amount 手续费金额
	 * @param name 描述
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月28日
	 */
	private ResultInfo countPoundage(t_scroe_rule scroeRule,t_scroe_rule deductionSettings,t_scroe tScroe,double amount,String name,String title){
		ResultInfo result = new ResultInfo();
//		是否使用积分抵扣手续费
		if(tScroe.scroe_switch == 0){
			result.code = 1;
			result.obj = amount;
			return result;
		}

		//得到积分抵扣手续费比例  最大抵扣比例
		double scale1 = Arith.div(deductionSettings.amount, 100, 2); //deductionScale1.divide(deductionScale).doubleValue();

//		可抵扣金额
		double amountScale = Arith.div(Arith.mul(scale1, amount),1,2);
		//抵扣手续费需要积分
		double totalScale = Arith.divUp(Arith.mul(amountScale, scroeRule.scroe), scroeRule.amount, 0);
		//需要扣除的总积分
		int count =(new Double(totalScale)).intValue();
		
		//积分足够抵扣除手续费的情况
		if ( count < Arith.add(tScroe.scroe, tScroe.bid_scroe) && count>0){
			
			result = scroeDeductionPoundage(tScroe,scroeRule,name, count);
			if (result.code < 1){
				return result;
			}
			//通知用户
			t_user user = userService.findByID(tScroe.user_id);
				Map<String, Object> sceneParame = new HashMap<String, Object>();
				sceneParame.put("user_name", user.company_full_name==null ?user.name:user.company_full_name );
				sceneParame.put("title", title );
				sceneParame.put("name", name );
				sceneParame.put("scroe", count );
				sceneParame.put("amount", amountScale );
				noticeService.sendSysNotice(tScroe.user_id, NoticeScene.CREDIT_POINTS, sceneParame);
			result.obj = Arith.sub(amount, amountScale);
			return result;
		}else{
			result.code = 1 ;
			result.msg = "抵扣积分为0！";
			result.obj = amount;
			return result;
		}
		
	}
	/**
	 * 积分扣除(积分抵扣手续)
	 * @param tScroe 积分账户对象
	 * @param scrowRule 积分规则对象
	 * @param name 描述
	 * @return
	 * @author binghui.zhou
	 * @param scroe  扣除的积分
	 * @createDate 2017年8月26日
	 */
	public ResultInfo scroeDeductionPoundage(t_scroe tScroe,t_scroe_rule scrowRule,String name, int scroe){
		ResultInfo result = new ResultInfo();
//		先扣除投资积分
		int bid_scroe = 0;
		int financing_scroe = 0;
		if(tScroe.bid_scroe >= scroe){
			 bid_scroe = scroe;
		}else{
			bid_scroe = tScroe.bid_scroe;
			financing_scroe = scroe-tScroe.bid_scroe;
		}
		boolean updScroe = deductionScroe(tScroe.id,financing_scroe,bid_scroe,0);
		if (!updScroe){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "扣除账户积分失败");
			result.code = -1;
			result.msg = "扣除账户积分失败";
			return result;
		}
		
		t_scroe_take_notes takeNotes = new t_scroe_take_notes();
		takeNotes.name = name;
		takeNotes.time = new Date();
		takeNotes.scroe_id = tScroe.id;
		takeNotes.scroe_rule_id = scrowRule.id;
		takeNotes.scroe = -scroe;
		takeNotes.type = scrowRule.type;
		boolean  takeBln = scroeTakeNotesService.saveTakeNotes(takeNotes);
		if (!takeBln){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "积分记录新增失败");
			result.code = -1;
			result.msg = "积分记录新增失败";
			return result;
		}
		
		result.code = 1;
		result.msg = "积分扣除成功";
		return result;
	}
	
	/**
	 * 积分提现(积分提现)
	 * @param tScroe 积分账户对象
	 * @param scrowRule 积分规则对象
	 * @param name 描述
	 * @return
	 * @author binghui.zhou
	 * @param scroe  扣除的积分
	 * @createDate 2017年8月26日
	 */
	public ResultInfo scroeWithdraw(t_scroe tScroe,t_scroe_rule scrowRule,String name, int scroe){
		ResultInfo result = new ResultInfo();
		boolean updScroe = deductionScroe(tScroe.id,scroe,0,scroe);
		if (!updScroe){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "扣除账户积分失败");
			result.code = -1;
			result.msg = "扣除账户积分失败";
			return result;
		}
		
		t_scroe_take_notes takeNotes = new t_scroe_take_notes();
		takeNotes.name = name;
		takeNotes.time = new Date();
		takeNotes.scroe_id = tScroe.id;
		takeNotes.scroe_rule_id = scrowRule.id;
		takeNotes.scroe = -scroe;
		takeNotes.type = scrowRule.type;
		boolean  takeBln = scroeTakeNotesService.saveTakeNotes(takeNotes);
		if (!takeBln){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "积分记录新增失败");
			result.code = -1;
			result.msg = "积分记录新增失败";
			return result;
		}
		
		result.code = 1;
		result.msg = "积分扣除成功";
		return result;
	}
	
	/**
	 * 积分添加
	 * @param tScroe 积分账户对象
	 * @param scrowRule //积分规则兑现
	 * @param name 描述
	 * @param amount 金额（投资金额或者融通金额）
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月26日
	 */
	public ResultInfo addScroe(t_scroe tScroe,String  scroeRuleKey,String name,double amount,String title){
		ResultInfo result = new ResultInfo();
		t_scroe_rule scrowRule = scroeRuleService.findScroeRule(scroeRuleKey);
		//根据金额计算积分
		int scroe = addCountScroe(amount,scrowRule.scroe,scrowRule.amount);
		if(scroe <=0 ){
			result.code = 1;
			result.msg = "获得积分需要大于0";
			return result;
		}
		int bid_scroe = 0;
		if(scroeRuleKey.equals(ScroeRuleKey.INVEST_SCROE)){
			bid_scroe = scroe;
			scroe = 0;
		}
		boolean updScroe = addDeductionScroe(tScroe.id,scroe,bid_scroe);
		if (!updScroe){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "新增账户积分失败");
			result.code = -1;
			result.msg = "新增账户积分失败";
			return result;
		}
		
		t_scroe_take_notes takeNotes = new t_scroe_take_notes();
		takeNotes.name = name;
		takeNotes.time = new Date();
		takeNotes.scroe_id = tScroe.id;
		takeNotes.scroe_rule_id = scrowRule.id;
		takeNotes.scroe = scroe+bid_scroe;
		takeNotes.type = scrowRule.type;
		boolean  takeBln = scroeTakeNotesService.saveTakeNotes(takeNotes);
		if (!takeBln){
			LoggerUtil.error(true, "ScroeService scroeWithdraw", "积分记录新增失败");
			result.code = -1;
			result.msg = "积分记录新增失败";
			return result;
		}
		//通知用户
		t_user user = userService.findByID(tScroe.user_id);
			Map<String, Object> sceneParame = new HashMap<String, Object>();
			sceneParame.put("user_name", user.company_full_name==null ?user.name:user.company_full_name );
			sceneParame.put("title", title );
			sceneParame.put("name", name );
			sceneParame.put("scroe", scroe+bid_scroe );
			noticeService.sendSysNotice(tScroe.user_id, NoticeScene.GET_POINT, sceneParame);
		result.code = 1;
		result.msg = "积分增加成功";
		return result;
	}
	
	/**
	 * 计算积分
	 * @param amount 金额（投资金额或者融通金额）
	 * @param ruleScroe 规则积分比例
	 * @param ruleAmount 规则积分金额
	 * @return
	 * @author binghui.zhou
	 * @createDate 2017年8月26日
	 */
	private int addCountScroe(double amount,int ruleScroe, int ruleAmount){
		
		double scroe = Arith.mul(amount, Arith.div(ruleScroe, ruleAmount, 2));
		
		
		return (new Double(scroe)).intValue();
	}
	
	/**
	 * 是否使用积分抵扣手续费开关 
	 * @param scroe_switch  是否使用积分抵扣手续费：0默认未使用 1使用
	 * @return
	 * @author binghui.zhou
	 * @param tScroe_id 
	 * @createDate 2017年8月28日
	 */
	public ResultInfo updateScroeSwitch(int scroe_switch,t_scroe tScroe) {
		ResultInfo result = new ResultInfo();
		int type=scroeDao.updateScroeSwitch(scroe_switch,tScroe.id);
		if (type < 1){
			result.code = -1;
			result.msg = "使用积分抵扣手续状态更新失败";
			return result;
		}
		result.code = 1;
		result.msg = "使用积分抵扣手续状态更新成功";
		return result;
	}
}
